<!-- 基础表格组件 -->

<!-- 属性 -->
<!-- 配置名称 | 类型 | 用途 | 返回值 | 默认值 | 必填 | 说明 -->
<!-- init-table-method     | Function | 初始化表格数据   | Promise<any> | null                  | * | 无 -->
<!-- condition-method      | Function | 组织表格筛选数据 | Object       | () => { return null } | - | 无 -->
<!-- refresh-key           | String   | 主动刷新表格     | -            | 'xxxxxx'              | - | 无 -->
<!-- storage-condition     | Boolean  | 缓存搜索条件     | -            | false                 | - | 如果需要实现搜索条件回填，需要手动实现restore-search事件 -->
<!-- attributes            | Object   | 其他属性        | -            | {}                    | - | 无 -->

<!-- 事件 -->
<!-- 事件名 | 说明 | Type -->
<!-- selection-change | 选中行变化时触发      | (val: any) => void -->
<!-- page-change      | 页码变化时触发        | (val: any) => void -->
<!-- data-change      | 数据变化时触发        | (val: any) => void -->
<!-- restore-search   | 搜索条件回填时触发    | (val: any) => void -->
<!-- loading-change   | loading状态变化时触发 | (val: boolean) => void -->

<!-- 插槽 -->
<!--
  #default: 各个列的配置
-->

<!-- expose -->
<!-- 方法名 | 说明 | Type -->
<!-- 无 -->
<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import { useRestoreSearch } from '@/hooks/useRestoreSearch'

interface Props {
  initTableMethod: (option: any) => Promise<any>
  conditionMethod?: () => any
  refreshKey?: string
  storageCondition?: boolean
  attributes?: any
}

const {
  initTableMethod,
  conditionMethod = () => {
    return null
  },
  refreshKey = `${new Date().getTime()}`,
  storageCondition = false,
  attributes = {},
} = defineProps<Props>()

const emit = defineEmits<{
  (e: 'selection-change', val: any): void
  (e: 'page-change', val: any): void
  (e: 'data-change', val: any): void
  (e: 'restore-search', val: any): void
  (e: 'loading-change', val: any): void
}>()

const bindAttributes = {}
Object.assign(bindAttributes, attributes)

const bindPaginationHeight = ref('80px')

const baseTableRef = ref()

// 缓存搜索项
const route = useRoute()
const moduleKey = route.path
const {
  setSearchStorage,
  setPageNumStorage,
  setPageSizeStorage,
  restoreSearchStorage,
  restorePageNumStorage,
  restorePageSizeStorage,
} = useRestoreSearch(moduleKey)

const pageNum = ref(1)
watch(pageNum, () => {
  emit('page-change', {})
  initTableData(true)
})
const pageSize = ref(restorePageSizeStorage() || 10)
watch(pageSize, () => {
  emit('page-change', {})
  initTableData(true)
})
const total = ref(0)

const loading = ref(false)

const tableData = ref<Array<any>>([])

// 排序相关
let sortitem: any = null
const handleSortChange = ({ prop, order }: any) => {
  // const target = sortableArr.find((item: any) => item.prop === prop)
  // if (target) {
  //   target.order = order
  // } else {
  //   sortableArr.push({ prop, order })
  // }
  sortitem = { prop, order }
  initTableData()
}

const initTableData = (initiative = false) => {
  loading.value = true
  // 初始化页数
  if (storageCondition && !initiative) {
    // 如果是被动刷新页面，则设置为缓存的页数
    pageNum.value = restorePageNumStorage()
  }
  const option: Record<string, any> = {
    current: pageNum.value,
    size: pageSize.value,
  }
  // 设置页数缓存
  if (storageCondition) {
    setPageNumStorage(pageNum.value)
    setPageSizeStorage(pageSize.value)
  }
  // 如果是被动刷新页面，则取出缓存的搜索条件
  let reconds = {}
  if (storageCondition && !initiative) {
    reconds = restoreSearchStorage()
    emit('restore-search', reconds)
  }
  // 页面发送来的筛选条件
  const conds = conditionMethod()
  if (storageCondition) {
    setSearchStorage(conds)
  }
  // 组织最终筛选条件
  const conditions: any = {}
  Object.assign(conditions, reconds, conds)
  if (conditions) {
    Object.keys(conditions).map((key) => {
      option[key] = conditions[key]
    })
  }
  // 组织排序条件
  if (sortitem) {
    if (sortitem.order) {
      option[sortitem.prop] = sortitem.order
    }
  }
  // 获取数据
  initTableMethod(option)
    .then((res) => {
      total.value = parseInt(res?.total) || 0
      if (res) {
        tableData.value = res.list
        emit('data-change', res.list)
      } else {
        tableData.value = []
        emit('data-change', [])
      }
    })
    .catch(() => {
      total.value = 0
      tableData.value = []
      emit('data-change', [])
    })
    .finally(() => {
      loading.value = false
    })
}

const handleSelectionChange = (val: any) => {
  emit('selection-change', val)
}

const refresh = () => {
  pageNum.value = 1
  sortitem = null
  baseTableRef.value.clearSort()
  initTableData(true)
}

const refreshStay = () => {
  initTableData(true)
}

// 主动刷新表单逻辑
watch(
  () => refreshKey,
  () => {
    refresh()
  },
)

// loading状态通知
watch(loading, (newVal) => {
  emit('loading-change', newVal)
})

defineExpose({
  baseTableRef,
  refresh,
  refreshStay,
})

onMounted(() => {
  initTableData()
})
</script>

<template>
  <div class="base-table-wrapper">
    <div class="table-container">
      <el-table
        ref="baseTableRef"
        v-loading="loading"
        :data="tableData"
        style="width: 100%"
        height="100%"
        v-bind="bindAttributes"
        @selection-change="handleSelectionChange"
        @sort-change="handleSortChange"
      >
        <slot></slot>
      </el-table>
    </div>
    <div class="pagination-container">
      <el-pagination
        v-model:current-page="pageNum"
        v-model:page-size="pageSize"
        background
        layout="total, sizes, prev, pager, next"
        :total="total"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.base-table-wrapper {
  width: 100%;
  height: 100%;
  .table-container {
    width: 100%;
    height: calc(100% - v-bind(bindPaginationHeight));
    .el-table {
      --el-table-header-text-color: #424a57 !important;
      --el-table-header-bg-color: #f7f8fa !important;
      :deep(.el-table__inner-wrapper::before) {
        background-color: rgba(255, 255, 255, 0);
      }
      :deep(.el-table__cell) {
        padding: 12px 0;
      }
    }
  }
  .pagination-container {
    width: 100%;
    height: v-bind(bindPaginationHeight);
    display: flex;
    flex-direction: flex-end;
    justify-content: center;
  }
}
</style>
